package com.tongcao.cn.daiyu.loader;

import com.google.common.base.Strings;
import com.tongcao.cn.daiyu.Handler;
import com.tongcao.cn.util.ClassLoaderUtil;
import com.tongcao.cn.util.DomHelper;
import org.slf4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author:tongcao
 * @Date:2019/1/11 15:13
 * Description:
 */
public class CommandLoader {

    private static final Logger logger = org.slf4j.LoggerFactory.getLogger(CommandLoader.class);

    public static final String CMD = "cmd";
    public static final String CLAZZ = "class";
    public static final String NEED_LOGIN_CHCK = "needLoginCheck";
    /**
     * cmd--hanlder
     */
    public Map<String, Handler> handlers;

    /**
     * cmd--cmd
     */
    public Map<String, String> nameHolder;

    public Map<String, Integer> needLogin;

    public CommandLoader() {
        needLogin = new ConcurrentHashMap<>();
    }

    private static CommandLoader instance = new CommandLoader();

    public static CommandLoader getInstance() {
        return instance;
    }


    public Handler getHandler(String cmd) {
        return handlers.get(cmd);
    }

    public String getName(String cmd) {
        return nameHolder.get(cmd);
    }


    /**
     * 读取配置(xml)
     *
     * @param path
     */
    public void load(String path) throws Exception {
        Map<String, Handler> tmpHandlers = new ConcurrentHashMap<String, Handler>();
        Map<String, String> tmpNameHolder = new ConcurrentHashMap<String, String>();
        InputStream is = null;
        try {
            is = ClassLoaderUtil.getResourceAsStream(path, CommandLoader.class);
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            InputSource source = new InputSource(is);
            source.setSystemId(path);
            Document doc = DomHelper.parse(source);
            if (doc != null) {
                NodeList nodeList = doc.getElementsByTagName("command");
                for (int i = 0; i < nodeList.getLength(); i++) {
                    Node node = nodeList.item(i);
                    if (node.getNodeType() == Node.ELEMENT_NODE) {
                        NodeList list = node.getChildNodes();
                        for (int j = 0; j < list.getLength(); ++j) {
                            Node childNode = list.item(j);
                            if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                                Element element = (Element) childNode;
                                String cmd = element.getAttribute(CMD);
                                String className = element.getAttribute(CLAZZ);
                                String needLoginCheck = element.getAttribute(NEED_LOGIN_CHCK);

                                if (Strings.isNullOrEmpty(cmd)) {
                                    continue;
                                }
                                tmpNameHolder.put(cmd, className);

                                try {
                                    Class<?> handlerClassName = Class.forName(className);
                                    if (handlerClassName == null) {
                                        continue;
                                    }
                                    Handler handler = (Handler) handlerClassName.newInstance();
                                    tmpHandlers.put(cmd, handler);
                                    if (needLoginCheck != null && needLoginCheck.equals("false")) {
                                        needLogin.put(cmd, 0);
                                    }
                                    logger.info("load cmd [" + cmd + "] class [" + className + "] succ");
                                } catch (Exception e) {
                                    logger.error("class" + className + "not found");
                                }
                            }
                        }
                    }
                }
                handlers = tmpHandlers;
                nameHolder = tmpNameHolder;
            } else {
                String errMsg = "read command from " + path + " fail, doc is null ";
                logger.error(errMsg);
                throw new Exception(errMsg);
            }
        } catch (Exception e) {
            String errMsg = "read command from " + path + " fail ";
            logger.error(errMsg);
            throw new Exception(errMsg, e);
        }
    }
}
